package org.xtframe.sql.verify;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import net.sf.json.JSONObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xtframe.sql.SqlDataVerify.VerifyType;
import org.xtframe.sql.PreparedParameter;
import org.xtframe.sql.VerifyBase;
import org.xtframe.util.CommonUtil;

public class PartitionTableVerify implements VerifyBase {
	
	private final Log logger = LogFactory.getLog(getClass());
	
	// Sql分区表(Oracle)替换参数（替换、检查）
	public enum PartitionTableParameter {
		YYYY, YYYYMM
	}
	
	private int position = -1;
	
	private String tableName = null;
	
	private PartitionTableParameter format = null;

	public void init(JSONObject data) {
		if(data.has("position")) this.position = data.optInt("position");
		if(data.has("table")) this.tableName = data.optString("table");
		if(data.has("format")) this.format = PartitionTableParameter.valueOf(data.optString("format").toUpperCase());
	}

	public int getPosition() {
		return this.position;
	}

	public VerifyType getXtype() {
		return VerifyType.replace;
	}

	public boolean check(List<String> parameters) {
		return false;
	}

	public String replace(List<String> parameters, List<PreparedParameter> preparedParameters) {
		String result = null;
		JSONObject o = CommonUtil.getJSONObject(parameters.get(position));
		if(o != null){
			try {
				String startDate = null;
				String endDate = null;
				if(o.has("startDate")) startDate = o.optString("startDate");
				if(o.has("endDate")) endDate = o.optString("endDate");
				if(format == PartitionTableParameter.YYYY) {
					result = partYearToTable(this.tableName, startDate, endDate);
				} else if(format == PartitionTableParameter.YYYYMM) {
					result = partMonthToTable(this.tableName, startDate, endDate);
				}
			} catch (Exception e) {
				logger.error("Oracle分区表拼接异常！");
			}
		}
		return result;
	}
	
	/**
     * 获取按年份分区的联表字符串
     * @param tableName
     * @param startDate
     * @param endDate
     * @return
     * @throws Exception
     */
    public static String partYearToTable(String tableName, String startDate, String endDate) throws Exception {
        DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
        DateFormat df2 = new SimpleDateFormat("yyyy");
        Date start = df1.parse(startDate);
        Date end = df1.parse(endDate);
        String strStart = df2.format(start);
        String strEnd = df2.format(end);
        
        int iStart = Integer.valueOf(strStart);
        int iEnd = Integer.valueOf(strEnd);
        if(iStart > iEnd) throw new Exception("开始时间小于结束时间！");
        
        StringBuffer result = new StringBuffer();
        if(iStart == iEnd){
            result.append("(select * from " + tableName + " partition(PART" + iStart + "))");
        } else {
            result.append("(select * from (");
            for(int i=iStart; i<=iEnd; i++){
                if(i != iStart) result.append(" union all ");
                result.append("select * from " + tableName + " partition(PART" + i + ")");
            }
            result.append("))");
        }

        return result.toString();
    }
    
    /**
     * 获取按月份分区的联表字符串
     * @param tableName
     * @param startDate
     * @param endDate
     * @return
     * @throws Exception
     */
    public static String partMonthToTable(String tableName, String startDate, String endDate) throws Exception {
        DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
        DateFormat df2 = new SimpleDateFormat("yyyyMM");
        Date start = df1.parse(startDate);
        Date end = df1.parse(endDate);
        String strStart = df2.format(start);
        String strEnd = df2.format(end);
        
        int iStart = Integer.valueOf(strStart);
        int iEnd = Integer.valueOf(strEnd);
        if(iStart > iEnd) throw new Exception("开始时间小于结束时间！");
        
        StringBuffer result = new StringBuffer();
        if(iStart == iEnd){
            result.append("(select * from " + tableName + " partition(PART" + strStart + "))");
        } else {
            Calendar gc = new GregorianCalendar();
            gc.setTime(start);
            Date current;
            String strCurrent;
            result.append("(select * from (select * from " + tableName + " partition(PART" + strStart + ")");
            while(true) {
                gc.add(Calendar.MONTH, 1);
                current = gc.getTime();
                strCurrent = df2.format(current);
                if(Integer.valueOf(strCurrent) > iEnd) break;
                
                result.append(" union all ");
                result.append("select * from " + tableName + " partition(PART" + strCurrent + ")");
            }
            result.append("))");
        }

        return result.toString();
    }

}
